

#include "SerialMemoryManager2.h"


SerialMemoryManager2::SerialMemoryManager2(MemoryTable *parMemoryTable, int parCollectorThreshold, int parNumClusters, float parLastThresold){


	memoryTable = parMemoryTable;
	memoryTableToReset = false;
	collector = new Collector();
	encoder = new Encoder(parNumClusters);
	collectorThreshold = parCollectorThreshold;
	lastThreshold = parLastThresold;
	updateThreshold = 1;
}

SerialMemoryManager2::~SerialMemoryManager2(){

	delete collector;
	delete encoder;
}


void SerialMemoryManager2::addEvent(PubPkt *pkt){


	string complexType = encoder->encode(pkt);
	cout << "Memory manager: Serial: message clustered in " << complexType  << "." << endl;

	boost::unordered_map<string, int>::iterator it = eventMap.find(complexType);
	if (it==eventMap.end()) {
		eventMap.insert(make_pair(complexType, 1));
	} else {
		it->second++;
	}
	cout << "Memory manager: Serial: start storing message..." << endl;
	memoryTable->computeInsertion(pkt, complexType);
	cout << "Memory manager: Serial: message stored." << endl;

}

void SerialMemoryManager2::addSubscription(BackSubPkt *pkt){

	collector->inspectSubscription(pkt);
	set<string> clustersMatched = encoder->encode(pkt);

	cout << "Memory manager: Serial: subscription clustered in ";
	for (set<string>::iterator it=clustersMatched.begin(); it!=clustersMatched.end(); it++) {
		string complexType = *it;
		cout << complexType << " ";
		boost::unordered_map<string, SubscribtionInfo>::iterator it2 = subscriptionMap.find(complexType);
		if (it2==subscriptionMap.end()) {
			SubscribtionInfo subInfo;
			subInfo.windowsList.push_back(pkt->getWindow());
			if (pkt->getOccurrence() == LAST){
				subInfo.countLast = 1;
			} else {
				subInfo.countLast = 0;
			}
			subscriptionMap.insert(make_pair(complexType, subInfo));
			//verifica se tabella da aggionare
			cout  << endl << endl << "----------------------------------------------------------------" << endl;
			cout << "Memory manager: Serial: start memory table updating..." << endl;
			cout << "cluster: " << complexType << "\t";
			cout << "subscriptions: 1" << "\t";
			cout << "window: " << pkt->getWindow() << "\t";
			bool resettable;
			float percentage = subInfo.countLast;
			if (percentage < lastThreshold){
				resettable = true;
			} else {
				resettable = false;
			}
			cout << "resettable: " << util::boolToString(resettable) << "\t" << endl;
			memoryTable->updateTable(complexType, 1, pkt->getWindow(), resettable, 0);
			cout << "Memory manager: Serial: memory table updated " << endl;
			cout << "----------------------------------------------------------------" << endl << endl;
		} else {
			it2->second.windowsList.push_back(pkt->getWindow());
			if (pkt->getOccurrence() == LAST){
				it2->second.countLast++;
			}
			cout  << endl << endl << "----------------------------------------------------------------" << endl;
			cout << "Memory manager: Serial: start memory table updating..." << endl;
			cout << "cluster: " << complexType << "\t";
			//vector<float> windowsVector = it2->second.windowsList;
			int subsCount =  it2->second.windowsList.size();//windowsVector.size();
			cout << "subscriptions: " << subsCount << "\t";
			//sort(windowsVector.begin(), windowsVector.end());
			if (it2->second.windowsList.size()%2==1){
				sort(it2->second.windowsList.begin(), it2->second.windowsList.end());
			}
			//float median = windowsVector[(int)windowsVector.size()/2];
			float median = it2->second.windowsList[( (int)it2->second.windowsList.size()-1)/2];
			cout << "window: " << median << "\t";
			bool resettable;
			float percentage = it2->second.countLast / subsCount;
			if (percentage < lastThreshold){
				resettable = true;
			} else {
				resettable = false;
			}
			cout << "resettable: " << util::boolToString(resettable) << "\t" << endl;
			memoryTable->updateTable(complexType, subsCount, median, resettable, 0);
			cout << "Memory manager: Serial: memory table updated " << endl;
			cout << "----------------------------------------------------------------" << endl << endl;
		}
	}
	cout << "." << endl;

	if (collector->getCount() == collectorThreshold){
		cout << endl;
		cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
		cout << "Memory manager: Serial: start encoder updating..." << endl;
		encoder->clear();
		boost::unordered_map<int, boost::unordered_map<string, vector<Type> > > collectorMap = collector->getMap();
		for (boost::unordered_map<int, boost::unordered_map<string, vector<Type> > >::iterator it=collectorMap.begin(); it!=collectorMap.end(); it++) {
			encoder->addEntry(it->first, it->second);
		}
		subscriptionMap.clear();
		eventMap.clear();
		collector->reset();
		memoryTableToReset = true;
		cout << "Memory manager: Serial: encoder updated" << endl; //
		cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl << endl;
	}
}


void SerialMemoryManager2::queryEventSet(BackSubPkt *pkt, Outbox &outbox){

	cout << "Memory manager: Serial: starting messages extraction..." << endl;
	memoryTable->computeExtraction(pkt, outbox.pkts);
	cout << "Memory manager: Serial: extraction terminated." << endl;
}
















